---
title: Architecture
summary: How the proxy is constructed, configured, invoked, and disposed.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-09-22
---

# Architecture

The hosted `FaxService` operation constructs a hand-written wrapper, `FaxServiceProxy`, which builds its own binding and endpoint address in code and constructs the generated `FaxServiceSoapClient` directly, bypassing the configured `<client><endpoint>` entirely.

## Proxy mechanism

| Aspect | Finding |
| --- | --- |
| Mechanism | Service Reference (svcutil / Add Service Reference) |
| Proxy type | `WCF.Legacy.Fax.FaxServiceSoapClient` |
| Base type | `System.ServiceModel.ClientBase<WCF.Legacy.Fax.FaxServiceSoap>` |
| Contract type | `WCF.Legacy.Fax.FaxServiceSoap` |
| Constructed in | `SAIF.Services.WCF.Services.LegacyProxies.FaxServiceProxy` constructor (`src\WCF\SAIF.Services.WCF.Host\Services\LegacyProxies\FaxServiceProxy.cs:29`) |
| Binding configured in | Code — `BasicHttpBinding` is constructed directly in the wrapper constructor |
| Address supplied by | Constructor argument — an `EndpointAddress` built from a string the wrapper receives |

## Construction path

The following diagram visualizes how a call reaches the remote service.

```mermaid
flowchart TD
    CALLER["FaxService.SendFax"] --> WRAP["FaxServiceProxy<br>hand-written wrapper"]
    WRAP --> BIND["BasicHttpBinding<br>TransportCredentialOnly"]
    BIND --> ADDR["EndpointAddress<br>from env service config"]
    ADDR --> PROXY["FaxServiceSoapClient<br>generated proxy"]
    PROXY --> REMOTE["Remote service<br>FaxService (ASMX)"]
    WRAP --> DISPOSE["Close only<br>no Abort fallback"]
```

## Hand-written wrapper

| Field | Value |
| --- | --- |
| **Type** | `SAIF.Services.WCF.Services.LegacyProxies.FaxServiceProxy` |
| **Source** | `src\WCF\SAIF.Services.WCF.Host\Services\LegacyProxies\FaxServiceProxy.cs` |
| **Visibility** | `internal` (`src\WCF\SAIF.Services.WCF.Host\Services\LegacyProxies\FaxServiceProxy.cs:9`) |
| **Implements** | `IDisposable` |
| **Responsibility** | Constructs the binding and endpoint, holds the generated proxy, maps `FaxRecipient`/file path arguments onto `FaxInfo`, and disposes the proxy |
| **Proxy lifetime** | Per `FaxServiceProxy` instance — one proxy per instance, held in a `readonly` field |

| Configuration applied | Value | Source |
| --- | --- | --- |
| `BasicHttpBinding` security mode | `BasicHttpSecurityMode.TransportCredentialOnly` | `src\WCF\SAIF.Services.WCF.Host\Services\LegacyProxies\FaxServiceProxy.cs:17` |
| Transport client credential | `HttpClientCredentialType.Windows` | `src\WCF\SAIF.Services.WCF.Host\Services\LegacyProxies\FaxServiceProxy.cs:27` |
| `MaxReceivedMessageSize` | `int.MaxValue` | `src\WCF\SAIF.Services.WCF.Host\Services\LegacyProxies\FaxServiceProxy.cs:19` |
| `MaxBufferSize` | `int.MaxValue` | `src\WCF\SAIF.Services.WCF.Host\Services\LegacyProxies\FaxServiceProxy.cs:20` |
| `ReaderQuotas.MaxArrayLength` | `int.MaxValue` | `src\WCF\SAIF.Services.WCF.Host\Services\LegacyProxies\FaxServiceProxy.cs:21-24` |
| Timeouts | None set — binding defaults apply | `src\WCF\SAIF.Services.WCF.Host\Services\LegacyProxies\FaxServiceProxy.cs:17-27` |

`MaxReceivedMessageSize`, `MaxBufferSize`, and `ReaderQuotas.MaxArrayLength` are all set to `int.MaxValue`, removing the guard that protects the process from an oversized response; see [Tech debt](tech-debt.md).

## Endpoint resolution

| Environment | Address | Resolved from | Changeable without a rebuild |
| --- | --- | --- | --- |
| Runtime (all environments) | The string returned by `env.GetConfigSetting(EnvironmentConfigKeys.FaxSoapServiceUrl)` | `src\WCF\SAIF.Services.WCF.Host\Services\FaxService.cs:21-25`, passed through `src\WCF\SAIF.Services.WCF.Host\Services\LegacyProxies\FaxServiceProxy.cs:12,29`; the literal key name and its per-environment values are supplied by the referenced `SAIF.Services.Common` package assembly and are unresolvable in this repository** | Yes — resolved per request from the environment service* |
| Configured (unreferenced) | `http://api.saif.com/webservices/SAIFFaxService/faxservice.asmx` | `<system.serviceModel><client><endpoint>` in `src\WCF\SAIF.Services.WCF.Host\Web.config:15` and `Web.Base.config:14` | No code path performs a configured-endpoint lookup for this contract, so this value is dead configuration* |
| Generation-time origin | `http://websvcprod/webservices/SAIFFaxService/faxservice.asmx` | `src\WCF\SAIF.Services.WCF.Host\Service References\Legacy.Fax\Reference.svcmap` (`MetadataSource Address`) and `faxservice.disco` | No — this was the address at the time the reference was generated, not the runtime address |

Binding, timeout, and credential-mode resolution:

| Setting | Value | Resolved from |
| --- | --- | --- |
| Binding (runtime) | `BasicHttpBinding` constructed in code | `src\WCF\SAIF.Services.WCF.Host\Services\LegacyProxies\FaxServiceProxy.cs:17` |
| Binding (configured, unreferenced) | `basicHttpBinding`, `bindingConfiguration="FaxServiceSoap"`, an all-defaults `<binding name="FaxServiceSoap"/>` | `src\WCF\SAIF.Services.WCF.Host\Web.config:15-16,40` |
| Contract name (configured) | `Legacy.Fax.FaxServiceSoap` | `src\WCF\SAIF.Services.WCF.Host\Web.config:16` |
| Timeouts | Not specified; transport default applies | No timeout set at `src\WCF\SAIF.Services.WCF.Host\Services\LegacyProxies\FaxServiceProxy.cs:17-27` and none on the configured binding at `Web.config:40` |
| Credential mode | `HttpClientCredentialType.Windows` over `BasicHttpSecurityMode.TransportCredentialOnly` — no credential value is read from configuration or code | `src\WCF\SAIF.Services.WCF.Host\Services\LegacyProxies\FaxServiceProxy.cs:17,27` |

Two findings on this table, recorded once and cross-referenced from [Tech debt](tech-debt.md): the configured `<client><endpoint>` is never consulted at run time because the wrapper supplies its own binding and address, and two stale endpoint declarations (`api.saif.com` and `websvcprod`) coexist with the third, authoritative, code-resolved address whose literal key name cannot be read from this repository**.

## Lifetime and disposal

| Aspect | Finding |
| --- | --- |
| Proxy lifetime | Per `FaxServiceProxy` instance, which is itself constructed once per `FaxService` instance and held in a `readonly` field |
| Disposal | `Close()` only, with no `Abort()` fallback |
| Faulted-channel handling | Not handled — `ClientBase<T>.Close()` on a faulted channel throws, so a failed `Send` can produce a second exception during disposal and mask the original failure* |
| Thread safety | Not determined from source |

## Integration points

| System | Type | Purpose |
| --- | --- | --- |
| `` `FaxService`† `` | SOAP service (ASMX) | Delivers the outbound fax submitted by the hosted `FaxService.SendFax` operation |

## Related documentation
- [Client index](index.md)
- [Overview](overview.md)
- [Contract](contract.md)
- [Operation map](operation-map.md)
- [Client reference](reference.md)
- [Consumption](consumption.md)
- [Dependencies](dependencies.md)
- [Tech debt](tech-debt.md)

> **Note:** Statements marked with `†` are derived from dependency library documentation via the Legends CLI. Statements marked with `*` were inferred from code structure or contextual evidence. Statements marked with `**` could not be confirmed; treat as unknown until verified.

## Sources
- `src\WCF\SAIF.Services.WCF.Host\Services\LegacyProxies\FaxServiceProxy.cs`
- `src\WCF\SAIF.Services.WCF.Host\Services\FaxService.cs`
- `src\WCF\SAIF.Services.WCF.Host\Web.config`
- `src\WCF\SAIF.Services.WCF.Host\Web.Base.config`
- `src\WCF\SAIF.Services.WCF.Host\Service References\Legacy.Fax\Reference.svcmap`
- `src\WCF\SAIF.Services.WCF.Host\Service References\Legacy.Fax\faxservice.disco`
